package com.bjb.vr.common.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjb.vr.common.ao.DeptUmsAccountAo;
import com.bjb.vr.common.ao.SysDeptAo;
import com.bjb.vr.common.constant.ThreadLocalConstant;
import com.bjb.vr.common.dto.*;
import com.bjb.vr.common.mapper.*;
import com.bjb.vr.common.result.BaseResult;
import com.bjb.vr.common.result.CommonResult;
import com.bjb.vr.common.utils.ThreadLocalUtil;
import com.bjb.vr.common.vo.DeptUmsAccountVo;
import com.bjb.vr.common.vo.DeptUmsRoleVo;
import com.bjb.vr.common.vo.SysDeptVo;
import com.bjb.vr.common.vo.UmsAccountVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author admin
 * @description 针对表【sys_dept】的数据库操作Service实现
 * @createDate 2022-08-23 16:58:30
 */
@Service
public class SysDeptService extends ServiceImpl<SysDeptMapper, SysDept> {

    private PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

    @Resource
    private SysDeptMapper sysDeptMapper;

    @Resource
    private UmsAccountMapper umsAccountMapper;

    @Resource
    private UmsUserRoleMapper umsUserRoleMapper;

    @Resource
    private UmsRoleMapper umsRoleMapper;

    @Resource
    private UmsOptAccountMapper optAccountMapper;

    @Resource
    private UmsOptUserRoleMapper optUserRoleMapper;

    @Resource
    private UmsOptRoleMapper optRoleMapper;


    /**
     * 查询组织架构树
     *
     * @param sysDeptAo
     * @return
     */
    public List<SysDeptVo> queryDeptTree(SysDeptAo sysDeptAo) {
        UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        LambdaQueryWrapper<SysDept> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(SysDept::getTenantId, umsAccountVo.getTenantId());
        List<SysDept> sysDeptList = sysDeptMapper.selectList(queryWrapper);
        List<SysDeptVo> sysDeptVos = buildShowData(sysDeptList);
        return sysDeptVos;
    }

    /**
     * 封装前端展示的层级关系
     *
     * @param sysDeptList
     * @return
     */
    private List<SysDeptVo> buildShowData(List<SysDept> sysDeptList) {
        // 过滤数据
        List<SysDeptVo> parentsList = new ArrayList<>();
        List<SysDeptVo> childrenList = new ArrayList<>();
        sysDeptList.stream().forEach(ss -> {
            if (ss.getParentId() == 0) {
                SysDeptVo sysDeptVo = new SysDeptVo();
                BeanUtils.copyProperties(ss, sysDeptVo);
                parentsList.add(sysDeptVo);
            } else {
                SysDeptVo sysDeptVo = new SysDeptVo();
                BeanUtils.copyProperties(ss, sysDeptVo);
                childrenList.add(sysDeptVo);
            }
        });

        // 封装子节点数据
        parentsList.stream().forEach(pp -> {
            List<SysDeptVo> sysTenantVos = buildChildrenData(pp, childrenList);
            pp.setChildren(sysTenantVos);
        });
        return parentsList;
    }


    /**
     * 递归设置子节点数据
     *
     * @param parentData
     * @param childrenList
     * @return
     */
    private List<SysDeptVo> buildChildrenData(SysDeptVo parentData, List<SysDeptVo> childrenList) {
        List<SysDeptVo> treeList = new ArrayList<>();
        childrenList.stream().forEach(cc -> {
            // 判断当前父节点是否有子节点
            if (parentData.getId().equals(cc.getParentId())) {
                cc.setChildren(buildChildrenData(cc, childrenList));
                treeList.add(cc);
            }
        });
        return treeList;
    }

    /**
     * 查询上级部门列表
     *
     * @param sysDeptAo
     * @return
     */
    public List<SysDeptVo> queryDeptList(SysDeptAo sysDeptAo) {
        UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        LambdaQueryWrapper<SysDept> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(SysDept::getTenantId, umsAccountVo.getTenantId());
        queryWrapper.orderByAsc(SysDept::getId);
        List<SysDept> sysDeptList = sysDeptMapper.selectList(queryWrapper);
        List<SysDeptVo> sysDeptVos = new ArrayList<>();
        sysDeptList.stream().forEach(ss -> {
            SysDeptVo sysDeptVo = new SysDeptVo();
            BeanUtils.copyProperties(ss, sysDeptVo);
            sysDeptVos.add(sysDeptVo);
        });
        return sysDeptVos;
    }

    /**
     * 查询部门员工列表
     *
     * @param sysDeptAo
     * @return
     */
    public List<UmsAccountVo> queryDeptStaffList(SysDeptAo sysDeptAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        LambdaQueryWrapper<UmsOptAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UmsOptAccount::getDeptId, sysDeptAo.getId());
        List<UmsOptAccount> umsAccounts = optAccountMapper.selectList(queryWrapper);
        List<UmsAccountVo> umsAccountVos = new ArrayList<>();
        umsAccounts.stream().forEach(us -> {
            UmsAccountVo umsAccountVo = new UmsAccountVo();
            BeanUtils.copyProperties(us, umsAccountVo);
            umsAccountVos.add(umsAccountVo);
        });
        return umsAccountVos;
    }

    /**
     * 新增部门
     *
     * @param sysDeptAo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean addDept(SysDeptAo sysDeptAo) {
        UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        try {
            for (Long leaderId : sysDeptAo.getLeaderId()) {
                SysDept sysDept = new SysDept();
                BeanUtils.copyProperties(sysDeptAo, sysDept);
                sysDept.setTenantId(umsAccountVo.getTenantId());
                sysDept.setLeaderId(leaderId);
                sysDeptMapper.insert(sysDept);
            }
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 查询上级部门是否存在
     *
     * @param sysDeptAo
     * @return
     */
    public boolean queryHigher(SysDeptAo sysDeptAo) {
        try {
            SysDept sysDept = sysDeptMapper.selectById(sysDeptAo.getId());
            if (Objects.isNull(sysDept)) {
                return false;
            }
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 编辑部门
     *
     * @param sysDeptAo
     * @return
     */
    public boolean updateDept(SysDeptAo sysDeptAo) {
        try {
            for (Long leaderId : sysDeptAo.getLeaderId()) {
                SysDept sysDept = new SysDept();
                BeanUtils.copyProperties(sysDeptAo, sysDept);
                sysDept.setLeaderId(leaderId);
                sysDeptMapper.updateById(sysDept);
            }
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 删除部门
     *
     * @param sysDeptAo
     * @return
     */
    public BaseResult deleteDept(SysDeptAo sysDeptAo) {
        // 查询是否存在子级部门
        LambdaQueryWrapper<SysDept> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysDept::getParentId, sysDeptAo.getId());
        List<SysDept> sysDepts = sysDeptMapper.selectList(queryWrapper);
        if (sysDepts.size() > 0) {
            return CommonResult.Fail("该部门存在子部门，请先删除子部门!");
        }
        // 查询是否存在用户
        LambdaQueryWrapper<UmsOptAccount> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(UmsOptAccount::getDeptId, sysDeptAo.getId());
        List<UmsOptAccount> umsAccounts = optAccountMapper.selectList(queryWrapper2);
        if (umsAccounts.size() > 0) {
            return CommonResult.Fail("该部门下有用户，请先删除用户!");
        }

        try {
            sysDeptMapper.deleteById(sysDeptAo.getId());
            return CommonResult.Ok();
        } catch (Exception e) {
            log.error(e.getMessage());
            return CommonResult.Fail("删除部门发生异常！");
        }
    }

    /**
     * 查询部门下用户列表
     * 不传部门ID时，默认查询该租户下所有的用户
     *
     * @param deptUmsAccountAo
     * @return
     */
    public Page<DeptUmsAccountVo> queryDeptUserList(DeptUmsAccountAo deptUmsAccountAo) {
        LambdaQueryWrapper<UmsOptAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Objects.nonNull(deptUmsAccountAo.getDeptId()), UmsOptAccount::getDeptId, deptUmsAccountAo.getDeptId());
        Page<UmsOptAccount> umsAccountPage = optAccountMapper.selectPage(new Page<>(deptUmsAccountAo.getCurrent(), deptUmsAccountAo.getSize()), queryWrapper);
        Page<DeptUmsAccountVo> deptUmsAccountPage = buildContentInfo(umsAccountPage);
        return deptUmsAccountPage;
    }

    /**
     * 封装返回用户对象
     *
     * @param umsAccountPage
     * @return
     */
    private Page<DeptUmsAccountVo> buildContentInfo(Page<UmsOptAccount> umsAccountPage) {
        Page<DeptUmsAccountVo> deptUmsAccountPage = new Page<>(umsAccountPage.getCurrent(), umsAccountPage.getSize(), umsAccountPage.getTotal());
        List<UmsOptAccount> records = umsAccountPage.getRecords();
        List<DeptUmsAccountVo> deptUmsAccountVos = new ArrayList<>();
        records.stream().forEach(ums -> {
            DeptUmsAccountVo umsAccountVo = new DeptUmsAccountVo();
            BeanUtils.copyProperties(ums, umsAccountVo);
            // 查询角色名称
            String roleName = umsUserRoleMapper.queryRoleNameByUserId(ums.getUserId());
            umsAccountVo.setRoleName(roleName);
            // 查询部门名称
            SysDept sysDept = sysDeptMapper.selectById(ums.getDeptId());
            umsAccountVo.setDeptName(sysDept.getDeptName());
            deptUmsAccountVos.add(umsAccountVo);
        });
        deptUmsAccountPage.setRecords(deptUmsAccountVos);
        return deptUmsAccountPage;
    }

    /**
     * 查询角色列表
     *
     * @return
     */
    public List<DeptUmsRoleVo> queryDeptRoleList() {
        List<DeptUmsRoleVo> deptUmsRoleVos = umsRoleMapper.queryRoleInfos();
        return deptUmsRoleVos;
    }

    /**
     * 新增用户
     *
     * @param deptUmsAccountAo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean addDeptUser(DeptUmsAccountAo deptUmsAccountAo) {
        UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        UmsOptAccount optAccount = new UmsOptAccount();
        BeanUtils.copyProperties(deptUmsAccountAo, optAccount);
        optAccount.setTenantId(umsAccountVo.getTenantId());
        optAccount.setPassword(passwordEncoder.encode(deptUmsAccountAo.getPassword()));
        try {
            // 新增账号
            optAccountMapper.insert(optAccount);

            // 关联账号和角色信息
            UmsUserRole umsUserRole = new UmsUserRole();
            umsUserRole.setUserId(optAccount.getUserId());
            umsUserRole.setRoleId(deptUmsAccountAo.getRoleId());
            umsUserRole.setTenantId(umsAccountVo.getTenantId());
            umsUserRoleMapper.insert(umsUserRole);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 编辑用户
     *
     * @param deptUmsAccountAo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean updateDeptUser(DeptUmsAccountAo deptUmsAccountAo) {
        UmsOptAccount optAccount = new UmsOptAccount();
        BeanUtils.copyProperties(deptUmsAccountAo, optAccount);
        if (StringUtils.isNotBlank(deptUmsAccountAo.getPassword())) {
            optAccount.setPassword(passwordEncoder.encode(deptUmsAccountAo.getPassword()));
        }

        try {
            // 更新账号
            optAccountMapper.updateById(optAccount);

            // 关联账号和角色信息
            UmsOptUserRole optUserRole = new UmsOptUserRole();
            optUserRole.setRoleId(deptUmsAccountAo.getRoleId());
            LambdaQueryWrapper<UmsOptUserRole> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UmsOptUserRole::getUserId, deptUmsAccountAo.getId());
            optUserRoleMapper.update(optUserRole, queryWrapper);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean removeDeptUser(DeptUmsAccountAo deptUmsAccountAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        try {
            // 删除账号
            optAccountMapper.deleteById(deptUmsAccountAo.getId());

            // 删除关联账号和角色信息
            LambdaQueryWrapper<UmsOptUserRole> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UmsOptUserRole::getUserId, deptUmsAccountAo.getId());
            optUserRoleMapper.delete(queryWrapper);

            // 如果有部门的负责人是此用户，那么设置为空
            sysDeptMapper.updateLeaderByLeaderId(deptUmsAccountAo.getId());
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }
}




